#!/usr/bin/env python
# -*- coding: utf-8 -*-

# This project is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# 
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This project is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Tutoo Installer.  If not, see <http://www.gnu.org/licenses/>.

import os

class Save_Changes():
	def __init__(self, objects, n_objs=None):
		print 'Initiate Save_changes'
		self.objects = objects
		self.n_objs = n_objs
		self._makedirs()
		print 'all make dirs finished'

	def run(self):
		self.is_ac_tlm_router_cpp()
		self.is_ac_tlm_router_h()
		self.plataform_main_cpp()
		self.make_defs()
		self.sw_hello_world()
		self.copy_all_stuffs()

	def is_ac_tlm_router_cpp(self):
		file_in = os.path.join('files','read','is','ac_tlm_router.cpp.in')
		file_out = os.path.join('files','write','arp','is','ac_tlm_router','ac_tlm_router.cpp')
		prog = self._read_file(file_in)
		base = {'target_export': 'target_export_%s("%s"),\n\t',
				'dm_port': 'DM_port_%s("%s", %sU),\n\t',
				'target_export_init': 'target_export_%s( *this );\n\t'}

		placeholders = {'%TARGET_EXPORT%': '',
						'%DM_PORT%': '',
						'%TARGET_EXPORT_INIT%': ''}

		for obj in self.objects:
			if obj.get_type() == 'proc':
				placeholders['%TARGET_EXPORT%'] += base['target_export'] % (obj.get_name(), obj.get_name())
				placeholders['%TARGET_EXPORT_INIT%'] += base['target_export_init'] % (obj.get_name())
			elif obj.get_type() == 'ip':
				placeholders['%DM_PORT%'] += base['dm_port'] % (obj.get_name(), obj.get_name(), obj.get_size())

		# Remove ,\n\t from last dm_port
		placeholders['%DM_PORT%'] = placeholders['%DM_PORT%'][:-3]

		for placeholder, value in placeholders.iteritems():
			prog = prog.replace('{%s}' % placeholder, value)

		self._write_file(file_out, prog)

	def is_ac_tlm_router_h(self):
		file_in = os.path.join('files','read','is','ac_tlm_router.h.in')
		file_out = os.path.join('files','write','arp','is','ac_tlm_router','ac_tlm_router.h')
		prog = self._read_file(file_in)

		base = {'dm_port': 'ac_tlm_port DM_port_%s;\n\t',
				'target_export': 'sc_export< ac_tlm_transport_if > target_export_%s;\n\t',
				'transport': 'if ((request.addr >= %s) && (request.addr <= %s)){response = DM_port_%s -> transport( request );}\n\t\t'
		}

		placeholders = {'%DM_PORT%': '', '%TARGET_EXPORT%': '', '%TRANSPORT%': ''}

		for obj in self.objects:
			if obj.get_type() == 'proc':
				placeholders['%TARGET_EXPORT%'] += base['target_export'] % obj.get_name()
			elif obj.get_type() == 'ip':
				placeholders['%DM_PORT%'] += base['dm_port'] % obj.get_name()
				placeholders['%TRANSPORT%'] += base['transport'] % (obj.get_start(), obj.get_end(), obj.get_name())

		for placeholder, value in placeholders.iteritems():
			prog = prog.replace('{%s}' % placeholder, value)

		self._write_file(file_out, prog)

	def plataform_main_cpp(self):
		# FIXME
		# 'procs_define': 'mips1 mips1_%s("mips1_%s");\n\t',
		file_in = os.path.join('files','read','platforms','main.cpp.in')
		file_out = os.path.join('files','write','arp','platforms','gen-plataform-mips','main.cpp')
		prog = self._read_file(file_in)

		base = {'includes': '#include "%s.%s"\n',
				'using': 'using user::%s;\n',
				'av_proc': 'char *av_%s[ac];\n\t',
				'procs_define': '%s %s("%s");\n\t',
				'is_define': '%s %s("%s");\n\t',
				'ip_define': '%s %s("%s");\n\t',
				'copy_av_proc': 'memcpy (av_%s, av, sizeof(av_%s));\n\t',
				'links_proc_is': '%s.DM_port(%s.target_export_%s);\n\t',
				'links_is_ip': '%s.DM_port_%s(%s.target_export);\n\t',
				'proc_iniciate': 'fprintf(stderr, "Iniciating %s\\n");\n\t%s.init(ac, av_%s);\n\n\t',
				'print_stats': '%s.PrintStat();\n\t',
				'print_time': '%s.ac_sim_stats.time = sc_simulation_time();\n\t%s.ac_sim_stats.print();\n\n\t',
				'return_and': 'sucess = sucess && %s.ac_exit_status;\n\t'
		}

		placeholders = {'%INCLUDES%': '', '%USING%': '', '%AV_PROC%': '', '%PROCS_DEFINE%': '',
						'%IS_DEFINE%': '', '%IP_DEFINE%': '', '%COPY_AV_PROC%': '',
						'%LINKS_PROC_IS%': '', '%LINKS_IS_IP%': '', '%PROC_INICIATE%': '', '%PRINT_STATS%': '',
						'%PRINT_TIME%': '', '%RETURN_AND%': '',
		}

		for obj in self.objects:
			if obj.get_type() == 'proc':
				placeholders['%AV_PROC%'] += base['av_proc'] % obj.get_name()
				placeholders['%PROCS_DEFINE%'] += base['procs_define'] % (obj.get_proc_type(),obj.get_name(),obj.get_name())
				placeholders['%COPY_AV_PROC%'] += base['copy_av_proc'] % (obj.get_name(), obj.get_name())
				placeholders['%PROC_INICIATE%'] += base['proc_iniciate'] % (obj.get_name(),obj.get_name(),obj.get_name())
				placeholders['%PRINT_STATS%'] += base['print_stats'] % obj.get_name()
				placeholders['%PRINT_TIME%'] += base['print_time'] % (obj.get_name(),obj.get_name())
				placeholders['%RETURN_AND%'] += base['return_and'] % obj.get_name()
				for link in obj.get_start_links():
					placeholders['%LINKS_PROC_IS%'] += base['links_proc_is'] % (obj.get_name(), link.get_name(), obj.get_name())
				if not base['includes'].replace('\n','') % (obj.get_proc_type(),'H') in placeholders['%INCLUDES%'].split('\n'):
					placeholders['%INCLUDES%'] += base['includes'] % (obj.get_proc_type(),'H')

			elif obj.get_type() == 'is':
				placeholders['%IS_DEFINE%'] += base['is_define'] % (obj.get_is_type(),obj.get_name(),obj.get_name())
				for link in obj.get_start_links():
					placeholders['%LINKS_IS_IP%'] += base['links_is_ip'] % (obj.get_name(), link.get_name(), link.get_name())
				if not base['includes'].replace('\n','') % ('ac_tlm_router','h')  in placeholders['%INCLUDES%'].split('\n'):
					placeholders['%INCLUDES%'] += base['includes'] % ('ac_tlm_router','h')
				if not base['using'].replace('\n','') % 'ac_tlm_router' in placeholders['%USING%'].split('\n'):
					placeholders['%USING%'] += base['using'] % 'ac_tlm_router'

			elif obj.get_type() == 'ip':
				if not base['includes'].replace('\n','') % (obj.get_ip_type(),'h') in placeholders['%INCLUDES%'].split('\n'):
					placeholders['%INCLUDES%'] += base['includes'] % (obj.get_ip_type(),'h')
				if not base['using'].replace('\n','') % obj.get_ip_type() in placeholders['%USING%'].split('\n'):
					placeholders['%USING%'] += base['using'] % obj.get_ip_type()
				placeholders['%IP_DEFINE%'] += base['ip_define'] % (obj.get_ip_type(),obj.get_name(),obj.get_name())

		for placeholder, value in placeholders.iteritems():
			prog = prog.replace('{%s}' % placeholder, value)

		self._write_file(file_out, prog)

	def make_defs(self):
		file_in = os.path.join('files','read','platforms','defs.arp')
		file_out = os.path.join('files','write','arp','platforms','gen-plataform-mips','defs.arp')
		prog = self._read_file(file_in)

		placeholders = {'%IP%': '', '%IS%': '', '%PROCESSOR%': '', '%SW%': '', '%WRAPPER%': ''}

		# SW and IS name are not changed.
		placeholders['%SW%'] = 'hello_world_gen'
		placeholders['%IS%'] = 'ac_tlm_router'

		for obj in self.objects:
			if obj.get_type() == 'proc' and not (obj.get_proc_type() in placeholders['%PROCESSOR%'].split(' ')):
				placeholders['%PROCESSOR%'] += obj.get_proc_type() + ' '
			elif obj.get_type() == 'ip' and not (obj.get_ip_type() in placeholders['%IP%'].split(' ')):
				placeholders['%IP%'] += obj.get_ip_type() + ' '

		for placeholder, value in placeholders.iteritems():
			prog = prog.replace('{%s}' % placeholder, str(value).rstrip())

		self._write_file(file_out, prog)

	def sw_hello_world(self):
		file_in = os.path.join('files','read','sw','hello_world_gen.c')
		file_out = os.path.join('files','write','arp','sw','hello_world_gen','hello_world_gen.c')
		prog = self._read_file(file_in)

		case = [
		'case %s:\n\t\t\t',
		'__asm__("addi $29, $29, %s");\n\t\t\t',
		'for(%s=0; %s < MAX; %s++)\n\t\t\t\t',
		'printf("Hello %s\\n");\n\t\t\t',
		'exit(0);\n\n\t\t','']

		base = {'variables_define': 'int %s;\n\t',
				'counter_addr': 'int *p = (int*) %s;\n\t',
				'switch_case': ''.join(case),
		}

		placeholders = {'%VARIABLES_DEFINE%': '', '%COUNTER_ADDR%': '', '%SWITCH_CASE%': ''}

		n = 0
		for obj in self.objects:
			if obj.get_type() == 'proc':
				name = obj.get_name()
				placeholders['%VARIABLES_DEFINE%'] += base['variables_define'] % obj.get_name()
				placeholders['%SWITCH_CASE%'] += base['switch_case']  % (n, n*-(32768/self.n_objs['proc']), name, name, name, name)
				n += 1

			elif obj.get_type() == 'ip' and obj.get_ip_type() == 'count':
				placeholders['%COUNTER_ADDR%'] += base['counter_addr'] % (obj.get_start())

		for placeholder, value in placeholders.iteritems():
			prog = prog.replace('{%s}' % placeholder, value)

		self._write_file(file_out, prog)

	def copy_all_stuffs(self):
		# copy = [(from, where),]
		copy = [
		(os.path.join('files','read','Makefile'),
		os.path.join('files','write','arp','Makefile')),
		(os.path.join('files','read','Makefile'),
		os.path.join('files','write','arp','Makefile.arp')),
		(os.path.join('files','read','platforms','Makefile'),
		os.path.join('files','write','arp','platforms','gen-plataform-mips','Makefile')),
		(os.path.join('files','read','platforms','Makefile'),
		os.path.join('files','write','arp','platforms','gen-plataform-mips','Makefile.arp')),
		(os.path.join('files','read','is','Makefile'),
		os.path.join('files','write','arp','is','ac_tlm_router','Makefile')),
		(os.path.join('files','read','is','Makefile'),
		os.path.join('files','write','arp','is','ac_tlm_router','Makefile.arp')),

		(os.path.join('files','read','sw','Makefile'),
		os.path.join('files','write','arp','sw','hello_world_gen','Makefile')),
		(os.path.join('files','read','sw','Makefile'),
		os.path.join('files','write','arp','sw','hello_world_gen','Makefile.arp')),
		]

		for i in copy:
			arq = self._read_file(i[0])
			self._write_file(i[1], arq)

	def _makedirs(self):
		base = os.path.join('files','write')
		self._remove_dir(base + os.sep + 'arp')
		dirs = [['','arp'],
		['','arp', 'is'],
		['','arp', 'is', 'ac_tlm_router'],
		['','arp', 'platforms'],
		['','arp', 'platforms', 'gen-plataform-mips'],
		['','arp', 'sw'],
		['','arp', 'sw', 'hello_world_gen'], ]

		for i in dirs:
			path = base + os.sep.join(i)
			if os.path.exists(path):
				os.rmdir(path)
			os.mkdir(path)

	def _remove_dir(self, directory):
		''' Remove directory if exists (remove all file in directory) '''
		path = directory
		if os.path.isdir(path):
			for i in os.listdir(directory):
				newpath = directory + os.sep + i
				if os.path.isdir(newpath):
					self._remove_dir(newpath)
				else:
					os.remove(newpath)
			os.rmdir(path)
		elif os.path.isfile(path):
			os.remove(path)
		else:
			print '%s not found' % path

	def _read_file(self, path_file):
		f = open(path_file)
		prog = f.read()
		f.close()
		return prog

	def _write_file(self, path_file, text):
		f = open(path_file, 'w')
		f.write(text)
		f.close()
